package com.seata.demo.order.service.impl;

import com.seata.demo.order.entity.Order;
import com.seata.demo.order.feign.TccAccountFeignClient;
import com.seata.demo.order.feign.TccStorageFeignClient;
import com.seata.demo.order.mapper.OrderMapper;
import com.seata.demo.order.service.TccOrderService;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class TccOrderServiceImpl implements TccOrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private TccStorageFeignClient storageFeignClient;

    @Autowired
    private TccAccountFeignClient accountFeignClient;

    @Override
    @GlobalTransactional(name = "create-order-tcc", rollbackFor = Exception.class)
    public void createOrder(String userId, String commodityCode, Integer count, BigDecimal money) {
        // 1. 创建订单（状态为待确认）
        Order order = new Order();
        order.setUserId(userId);
        order.setCommodityCode(commodityCode);
        order.setCount(count);
        order.setMoney(money);
        order.setStatus(0); // 0-待确认
        orderMapper.insert(order);
        BusinessActionContext businessActionContext = new BusinessActionContext();
        // 将订单ID存入上下文，供后续确认或回滚使用
        Map<String, Object> objectObjectHashMap = new HashMap<>();
        businessActionContext.setActionContext(objectObjectHashMap);
        Map<String, Object> actionContext = businessActionContext.getActionContext();
        actionContext.put("orderId", order.getId());
        businessActionContext.setActionContext(actionContext);

        // 2. 调用库存TCC的Try方法 可以使用kafka异步操作，解耦、削峰
        boolean storageResult = storageFeignClient.tryDeduct(commodityCode, count);
        if (!storageResult) {
            throw new RuntimeException("库存扣减预处理失败");
        }

        // 3. 调用账户TCC的Try方法
        boolean accountResult = accountFeignClient.tryDebit(userId, money);
        if (!accountResult) {
            throw new RuntimeException("账户扣减预处理失败");
        }
    }

    @Override
    public boolean confirm(BusinessActionContext context) {
        String xid = context.getXid();
        log.info("Order TCC Confirm阶段：xid={}", xid);
        Long orderId = Long.valueOf(context.getActionContext("orderId").toString());
        // 更新订单状态为已完成
        orderMapper.updateStatus(orderId, 1);
        return true;
    }

    @Override
    public boolean cancel(BusinessActionContext context) {
        String xid = context.getXid();
        log.info("Order TCC Confirm阶段：xid={}", xid);
        Long orderId = Long.valueOf(context.getActionContext("orderId").toString());
        // 更新订单状态为已取消
        orderMapper.updateStatus(orderId, 2);
        return true;
    }
}
